﻿using System;
using System.CodeDom;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using JBeamLibrary.Tools;
using JBeamLibrary.Types;
using JBeamLibrary.VehicleParts;
using JBeamLibrary.VehicleParts.Collections;
using JBeamLibrary.VehicleParts.Elements;
using JBeamLibrary.VehicleParts.Groups;
using Newtonsoft.Json;

namespace JBeamLibrary
{
    public class Vehicle : KeyedCollection<string, VehicleFile>// Dictionary<string, VehicleFile>
    {
        #region Fields

        private readonly ErrorManager _errorManager = new ErrorManager();
        private readonly VehicleConfigCollection _configurations = new VehicleConfigCollection();

        #endregion

        #region Properties

        /// <summary>Gets the vehicle name</summary>
        public string Name
        {
            get;
            private set;
        }

        /// <summary>Gets or sets the vehicle label</summary>
        public string Label
        {
            get;
            set;
        }

        /// <summary>Gets the folder holding the vehicle contents</summary>
        public string Folder
        {
            get { return GetVehicleFolder(Name); }
        }

        /// <summary>Checks whether the vehicle physically exists (the model must be present in the folder)</summary>
        public bool IsValid
        {
            get { return IsVehicleValid(Name); }
        }

        /// <summary>Returns a collection of all the parts in this vehicle</summary>
        public IEnumerable<VehiclePart> AllParts
        {
            get
            {
                return this.SelectMany(file => file);
                //return this.Aggregate(new List<VehiclePart>(), (list, cur) =>
                //{
                //    list.AddRange(cur);
                //    return list;
                //});
            }
        }

        /// <summary>Gets the different configurations available</summary>
        public VehicleConfigCollection Configurations { get { return _configurations; } }

        /// <summary>Gets or sets the beam scales</summary>
        public BeamScales BeamScales { get; set; }

        /// <summary>Gets or sets the node scales</summary>
        public NodeScales NodeScales { get; set; }

        /// <summary>Gets or sets the collision values</summary>
        public CollisionValues Collisions { get; set; }

        /// <summary>Gets the error manager for this vehicle</summary>
        public ErrorManager ErrorManager
        {
            get { return _errorManager; }
        }

        /// <summary>Gets a value indicating if the vehicle was opened with errors</summary>
        public bool HasErrors
        {
            get { return _errorManager.HasErrors; }
        }

        /// <summary>Gets the model file paths</summary>
        public IEnumerable<string> ReadableModelFilePaths
        {
            get { return GetReadableModelFilePaths(Name); }
        }

        /// <summary>Gets the total amount of nodes in the vehicle</summary>
        public int TotalNodeCount
        {
            get { return AllParts.Sum(p => p.NodeSection.Count); }
        }

        #endregion

        #region CTORs

        public Vehicle(string name)
        {
            Name = name;
            Collisions = new CollisionValues();
            BeamScales = new BeamScales();
            NodeScales = new NodeScales();
        }

        #endregion

        #region Methods

        public bool AddVehicleFile(string fileName)
        {
            if (Contains(fileName)) return false;
            Add(new VehicleFile(fileName, this));
            return true;
        }

        public bool RemoveVehicleFile(string fileName)
        {
            return Contains(fileName) && Remove(fileName);
        }

        public bool AddVehiclePart(string partName, string fileName)
        {
            if (!Contains(fileName)) AddVehicleFile(fileName);
            return this[fileName].AddPart(partName);
        }

        /// <summary>Removes a vehicle part from the vehicle</summary>
        /// <param name="partName"></param>
        /// /// <param name="fileName"></param>
        /// <returns></returns>
        public bool RemoveVehiclePart(string partName, string fileName)
        {
            return Contains(fileName) && this[fileName].RemovePart(partName);
        }

        /// <summary>Loads the vehicle contents</summary>
        public void Load()
        {
            /* Read vehicle config files */
            LoadConfig();

            /* Read the folder and add the vehicle files that are in the vehicle folder (not shared) */
            if (Directory.Exists(Folder))
            {
                foreach (var file in Directory.GetFiles(Folder, "*.jbeam"))
                    AddVehicleFile(Path.GetFileNameWithoutExtension(file));
            }

            /* Load or reload all files including shared parts */
            try
            {
                foreach (var file in this)
                    file.Load();
            }
            catch (Exception ex)
            {
                throw new InvalidDataException(string.Format("The vehicle '{0}' couldn't be loaded for the following reason:{1}{1}{2}", Label, Environment.NewLine, ex.Message), ex);
            }

            /* Read configuration files */
            LoadConfigurations();
        }

        /// <summary>Loads the vehicle configuration</summary>
        private void LoadConfig()
        {
            Label = GetVehicleLabel(Name);
        }

        private void LoadConfigurations()
        {
            LoadVehicleConfigs(this);
        }

        private void SaveConfigurations(bool compress = true)
        {
            SaveVehicleConfigs(this, compress);
        }

        /// <summary>Saves the vehicle contents</summary>
        public void Save(bool compress = false)
        {
            /* Create directory if needed */
            if (!Directory.Exists(Folder)) Directory.CreateDirectory(Folder);

            /* Save configuration */
            SaveConfig();

            /* Save all files */
            foreach (var file in this)
                file.Save(compress);

            /* Save the configurations */
            SaveConfigurations(compress);
        }

        public void SaveAs(string vehicleName, bool compress = false)
        {
            /* Create directory if needed */
            var folder = GetVehicleFolder(vehicleName);
            if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);

            /* Save configuration */
            SaveConfigAs(vehicleName);

            /* Save all jbeams */
            foreach (var file in this)
            {
                var fileFolder = Path.GetDirectoryName(file.FilePath);
                if (string.IsNullOrEmpty(fileFolder)) continue;

                var fileName = Path.GetFileName(file.FilePath);
                if (string.IsNullOrEmpty(fileName)) continue;

                if (fileName.StartsWith(Name))
                    fileName = fileName.Substring(Name.Length);
                fileName = vehicleName + fileName;
                fileFolder = folder;

                file.SaveAs(string.Format("{0}{1}", fileFolder, fileName), compress);
            }

            /* Copy contents */
            if (!Config.CopyAllVehicleContentsOnSave) return;
            foreach (var file in Directory.GetFiles(Folder).Where(f => f != null && !Path.GetExtension(f).ToUpperInvariant().Equals(".JBEAM")))
            {
                var fileName = Path.GetFileName(file).ToStringOrEmpty();
                if (fileName.Equals(ConfigurationManager.AppSettings["defVehicleNameFile"])) continue;

                if (fileName.ToUpperInvariant().StartsWith(Name.ToUpperInvariant()))
                    fileName = vehicleName + fileName.Substring(Name.Length);

                File.Copy(file, string.Format(@"{0}{1}", folder, fileName), true);
            }

            /* Save configurations */
            SaveConfigurations(compress);
        }

        /// <summary>Saves the vehicle configuration</summary>
        private void SaveConfig()
        {
            SetVehicleLabel(Name, Label);
        }

        /// <summary>Saves the vehicle configuration as</summary>
        private void SaveConfigAs(string name)
        {
            SetVehicleLabel(name, Label);
        }

        /// <summary>
        /// Copy all resources to another vehicle folder (without renaming except the model)
        /// </summary>
        /// <param name="vehicleName"></param>
        public void CopyResourcesTo(string vehicleName)
        {
            foreach (var file in Directory.GetFiles(Folder).Where(f => f != null && !Path.GetExtension(f).ToUpperInvariant().Equals(".JBEAM")))
            {
                var fileName = Path.GetFileName(file).ToStringOrEmpty();
                if (fileName.Equals(ConfigurationManager.AppSettings["defVehicleNameFile"])) continue;
                if (fileName.ToUpperInvariant().Equals("NAME.CS")) continue;

                /* Rename only the model */
                if (fileName.ToUpperInvariant().StartsWith(Name.ToUpperInvariant()) && Path.GetExtension(file).ToUpperInvariant().Equals(".DAE"))
                    fileName = vehicleName + fileName.Substring(Name.Length);

                var outFolder = GetVehicleFolder(vehicleName);
                File.Copy(file, string.Format(@"{0}{1}", outFolder, fileName), true);
            }
        }

        /// <summary>
        /// Copy all resources from another vehicle (without renaming except the model)
        /// </summary>
        /// <param name="vehicleName"></param>
        public void CopyResourcesFrom(string vehicleName)
        {
            var sourceFolder = GetVehicleFolder(vehicleName);
            foreach (var file in Directory.GetFiles(sourceFolder).Where(f => f != null && !Path.GetExtension(f).ToUpperInvariant().Equals(".JBEAM")))
            {
                var fileName = Path.GetFileName(file).ToStringOrEmpty();
                if (fileName.Equals(ConfigurationManager.AppSettings["defVehicleNameFile"])) continue;
                if (fileName.ToUpperInvariant().Equals("NAME.CS")) continue;

                /* Rename only the model */
                if (fileName.ToUpperInvariant().StartsWith(vehicleName.ToUpperInvariant()) && ".DAE;.OBJ;.3DS;.LWO".Contains(Path.GetExtension(file).ToUpperInvariant()))
                    fileName = Name + fileName.Substring(vehicleName.Length);

                File.Copy(file, string.Format(@"{0}{1}", Folder, fileName), true);
            }
        }

        /// <summary>Gets the error last message (data is cleared after being retrieved)</summary>
        /// <returns></returns>
        public string GetErrorText()
        {
            if (!HasErrors) return string.Empty;

            return _errorManager.GetErrorMessage(string.Format("Some errors were detected while loading vehicle '{0}'", Name));
        }

        /// <summary>Searches for a part with the given name</summary>
        /// <param name="partName"></param>
        /// <returns></returns>
        public VehiclePart FindPart(string partName)
        {
            return this.SelectMany(file => file).FirstOrDefault(part => part.Name.Equals(partName));
        }

        /// <summary>Searches for a slot with the given type name</summary>
        /// <param name="slotTypeName"></param>
        /// <returns></returns>
        public Slot FindSlot(string slotTypeName)
        {
            return
                this.SelectMany(file => file)
                    .SelectMany(part => part.Slots)
                    .FirstOrDefault(slot => slot.TypeName.Equals(slotTypeName));
        }

        /// <summary>Searches for a node by ID in the whole vehicle</summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        public Node FindNode(string nodeId)
        {
            return this.SelectMany(file => file).SelectMany(part => part.NodeSection.ElementCollection as NodeCollection).FirstOrDefault(node => node.Id.Equals(nodeId));
        }

        /// <summary>
        /// Returns the first node found at the provided position
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public Node FindNode(float x, float y, float z)
        {
            return
                this.SelectMany(file => file)
                    .SelectMany(part => part.NodeSection.Nodes)
                    .FirstOrDefault(node => node.PosX == x && node.PosY == y && node.PosZ == z);
        }

        /// <summary>Gets all parts linked to the specified slot type</summary>
        /// <param name="slotTypeName"></param>
        /// <returns></returns>
        public IEnumerable<VehiclePart> GetPartsPerSlot(string slotTypeName)
        {
            return AllParts.Where(part => part.SlotType.Equals(slotTypeName));
        }

        /// <summary>Updates the elements linked to a node when its id is changed</summary>
        /// <param name="oldId"></param>
        /// <param name="newId"></param>
        public void UpdateNodeLinks(string oldId, string newId)
        {
            /* Get all parts */
            var allParts = AllParts;

            /* Ref nodes */
            var allRefNodes = AllParts.Select(part => part.RefNodes);
            foreach (var refNodes in allRefNodes)
                if (refNodes.LeftNodeId.Equals(oldId))
                    refNodes.LeftNodeId = newId;
                else if (refNodes.RefNodeId.Equals(oldId))
                    refNodes.RefNodeId = newId;
                else if (refNodes.BackNodeId.Equals(oldId))
                    refNodes.BackNodeId = newId;
                else if (refNodes.UpNodeId.Equals(oldId))
                    refNodes.UpNodeId = newId;

            /* Beams */
            var allBeams = allParts
                .SelectMany(part => ((BeamCollection)part.BeamSection.ElementCollection))
                .Where(beam => beam.NodeId1.Equals(oldId) || beam.NodeId2.Equals(oldId));
            foreach (var beam in allBeams)
                if (beam.NodeId1.Equals(oldId))
                    beam.NodeId1 = newId;
                else beam.NodeId2 = newId;

            /* Triangles */
            var allTriangles = allParts
                .SelectMany(part => ((TriangleCollection)part.TriangleSection.ElementCollection))
                .Where(triangle => triangle.NodeId1.Equals(oldId) || triangle.NodeId2.Equals(oldId) || triangle.NodeId3.Equals(oldId));
            foreach (var triangle in allTriangles)
                if (triangle.NodeId1.Equals(oldId))
                    triangle.NodeId1 = newId;
                else if (triangle.NodeId2.Equals(oldId))
                    triangle.NodeId2 = newId;
                else triangle.NodeId3 = newId;

            /* Thrusters */
            var allThrusters = allParts
                .SelectMany(part => ((ThrusterCollection)part.ThrusterSection.ElementCollection))
                .Where(thruster => thruster.NodeId1.Equals(oldId) || thruster.NodeId2.Equals(oldId));
            foreach (var thruster in allThrusters)
                if (thruster.NodeId1.Equals(oldId))
                    thruster.NodeId1 = newId;
                else thruster.NodeId2 = newId;

            /* Internal cameras */
            var allInternalCameras = allParts
                .SelectMany(part => ((InternalCameraCollection)part.InternalCameraSection.ElementCollection));
            foreach (var internalCamera in allInternalCameras)
                if (internalCamera.NodeId1.Equals(oldId))
                    internalCamera.NodeId1 = newId;
                else if (internalCamera.NodeId2.Equals(oldId))
                    internalCamera.NodeId2 = newId;
                else if (internalCamera.NodeId3.Equals(oldId))
                    internalCamera.NodeId3 = newId;
                else if (internalCamera.NodeId4.Equals(oldId))
                    internalCamera.NodeId4 = newId;
                else if (internalCamera.NodeId5.Equals(oldId))
                    internalCamera.NodeId5 = newId;
                else if (internalCamera.NodeId6.Equals(oldId))
                    internalCamera.NodeId6 = newId;

            /* Hub-wheels */
            var allHubWheels = allParts
                .SelectMany(part => ((HubWheelsCollection)part.HubWheelSection.ElementCollection))
                .Where(hubWheel => hubWheel.NodeId1.Equals(oldId) || hubWheel.NodeId2.Equals(oldId) || hubWheel.NodeArmId.Equals(oldId));
            foreach (var hubWheel in allHubWheels)
                if (hubWheel.NodeId1.Equals(oldId))
                    hubWheel.NodeId1 = newId;
                else if (hubWheel.NodeId2.Equals(oldId))
                    hubWheel.NodeId2 = newId;
                else if (hubWheel.NodeArmId.Equals(oldId))
                    hubWheel.NodeArmId = newId;

            /* Hydros */
            var allHydros = allParts
                .SelectMany(part => ((HydroCollection)part.HydroSection.ElementCollection))
                .Where(hydro => hydro.NodeId1.Equals(oldId) | hydro.NodeId2.Equals(oldId));
            foreach (var hydro in allHydros)
                if (hydro.NodeId1.Equals(oldId))
                    hydro.NodeId1 = newId;
                else hydro.NodeId2 = newId;

            /* Props */
            var allprops = allParts
                .SelectMany(part => ((PropCollection)part.PropSection.ElementCollection))
                .Where(prop => prop.NodeIdRef.Equals(oldId) || prop.NodeIdX.Equals(oldId) || prop.NodeIdY.Equals(oldId));
            foreach (var prop in allprops)
                if (prop.NodeIdRef.Equals(oldId))
                    prop.NodeIdRef = newId;
                else if (prop.NodeIdX.Equals(oldId))
                    prop.NodeIdX = newId;
                else prop.NodeIdY = newId;

            /* Ropables */
            var allRopables = allParts.SelectMany(part => part.Ropables.Values).Where(ropable => ropable.NodeId.Equals(oldId));
            foreach (var ropable in allRopables)
                ropable.NodeId = newId;

            /* Ties */
            var allTies = allParts
                .SelectMany(part => ((TieCollection)part.TieSection.ElementCollection))
                .Where(tie => tie.NodeId.Equals(oldId));
            foreach (var tie in allTies)
                tie.NodeId = newId;
        }

        /// <summary>Rename nodes in the most logic way</summary>
        public void RefactorNodes()
        {
            var prefixList = new List<string>();

            foreach (var part in AllParts)
            {
                /* Data */
                var nodes = part.NodeSection.Nodes;
                if (nodes.Count == 0) continue;

                /* Determine prefix */
                var name = part.Name.Equals(Name)
                    ? Name[0].ToString(CultureInfo.InvariantCulture)
                    : part.Name;
                var prefix = (name.Length == 1 ? name : string.Join(string.Empty, name.Split('_').Select(s => s[0]))).ToLowerInvariant();
                while (prefixList.Contains(prefix))
                    prefix += 'x';
                prefixList.Add(prefix);

                /* Axis variables */
                var left = 0;
                var right = 0;
                var front = 0;
                var back = 0;
                var up = 0;
                var down = 0;

                /* Calculate average position of all nodes in the part */
                var avgX = nodes.Average(node => node.PosX);
                var avgY = nodes.Average(node => node.PosY);
                var avgZ = nodes.Average(node => node.PosZ);

                /* Sort nodes by X value */
                var nodesByX = nodes.OrderBy(node => node.PosX);
                foreach (var node in nodesByX)
                {
                    var builder = new StringBuilder();
                    if (node.PosX > avgX) builder.AppendFormat("{0}r", ++right);
                    else if (node.PosX < avgX) builder.AppendFormat("{0}l", ++left);

                    node.Id = string.Format("Refactoring_{0}{1}", prefix, builder);
                }

                /* Sort nodes by Y value */
                var nodesByY = nodesByX.OrderBy(node => node.PosY);
                foreach (var node in nodesByY)
                {
                    var builder = new StringBuilder();
                    if (node.PosY > avgY) builder.AppendFormat("{0}f", ++front);
                    else if (node.PosY < avgY) builder.AppendFormat("{0}b", ++back);

                    node.Id = string.Format("{0}{1}", node.Id, builder);
                }

                /* Sort nodes by Z value */
                var nodesByZ = nodesByY.OrderBy(node => node.PosZ);
                foreach (var node in nodesByZ)
                {
                    var builder = new StringBuilder();
                    if (node.PosZ > avgZ) builder.AppendFormat("{0}u", ++up);
                    else if (node.PosZ < avgZ) builder.AppendFormat("{0}d", ++down);

                    node.Id = string.Format("{0}{1}", node.Id, builder);
                }
            }

            foreach (var part in AllParts)
            {
                /* Data */
                var nodes = part.NodeSection.Nodes;
                if (nodes.Count == 0) continue;

                foreach (var node in nodes)
                    node.Id = node.Id.Replace("Refactoring_", string.Empty);
            }
        }

        #endregion

        #region Static methods

        /// <summary>Gets the folder holding all the vehicles</summary>
        /// <returns></returns>
        public static string GetRootFolder()
        {
            return string.Format(@"{0}\vehicles\", Config.GamePath);
        }

        /// <summary>Returns the folder containing the vehicle with the specified name</summary>
        /// <param name="vehicleName"></param>
        /// <returns></returns>
        public static string GetVehicleFolder(string vehicleName)
        {
            return string.Format(@"{0}{1}\", GetRootFolder(), vehicleName);
        }

        /// <summary>Cheks whether a vehicle exists or not (the model must be present in the directory)</summary>
        /// <param name="vehicleName"></param>
        /// <returns></returns>
        public static bool IsVehicleValid(string vehicleName)
        {
            var ext = ConfigurationManager.AppSettings["modelExtension"];
            var folder =
                Directory.Exists(vehicleName) ?
                string.Format(@"{0}\", vehicleName) :
                GetVehicleFolder(vehicleName);
            vehicleName = vehicleName.LastDelimitedPart(@"\");

            //return
            //    Directory.Exists(folder) &&
            //    Directory.GetFiles(folder, string.Format("*{0}", ext))
            //        .Any(dae => dae.ToLowerInvariant().EndsWith(string.Format(@"\{0}{1}", vehicleName, ext)));

            return
                Directory.Exists(folder) &&
                Directory.GetFiles(folder, string.Format("{0}.jbeam", vehicleName))
                .Any();
        }

        /// <summary>Gets the paths of the models present in the vehicle folder</summary>
        /// <param name="vehicleName"></param>
        /// <returns></returns>
        public static IEnumerable<string> GetReadableModelFilePaths(string vehicleName)
        {
            var folder =
                Directory.Exists(vehicleName) ?
                string.Format(@"{0}\", vehicleName) :
                GetVehicleFolder(vehicleName);
            vehicleName = vehicleName.LastDelimitedPart(@"\");

            return Directory.GetFiles(folder, "*.obj");
        }

        /// <summary>Returns the names of all the valid vehicles</summary>
        /// <returns></returns>
        public static IEnumerable<TaggedString> GetValidVehicles()
        {
            return
                Directory.GetDirectories(GetRootFolder())
                    .Where(IsVehicleValid)
                    .Select(vPath => vPath.LastDelimitedPart(@"\"))
                    .Select(s => new TaggedString(GetVehicleLabel(s), s));
        }

        /// <summary>Loads a vehicle</summary>
        /// <param name="vehicleName"></param>
        /// <returns></returns>
        public static Vehicle LoadVehicle(string vehicleName)
        {
            var vehicle = new Vehicle(vehicleName);
            vehicle.Load();
            return vehicle;
        }

        /// <summary>Saves a vehicle</summary>
        /// <param name="vehicle"></param>
        public static void SaveVehicle(Vehicle vehicle, bool compress = false)
        {
            vehicle.Save(compress);
        }

        /// <summary>Saves a vehicle under the specified name</summary>
        /// <param name="vehicle"></param>
        /// <param name="vehicleName"></param>
        public static void SaveVehicleAs(Vehicle vehicle, string vehicleName, bool compress = false)
        {
            vehicle.SaveAs(vehicleName, compress);
        }

        /// <summary>Gets the label of a vehicle</summary>
        /// <param name="vehicleName"></param>
        /// <returns></returns>
        public static string GetVehicleLabel(string vehicleName)
        {
            var filePath = string.Format("{0}{1}", GetVehicleFolder(vehicleName), ConfigurationManager.AppSettings["defVehicleNameFile"]);
            if (!File.Exists(filePath)) return vehicleName;

            var nameLines = File.ReadAllLines(filePath);
            if (nameLines.Length == 0) return vehicleName;

            var match = Regex.Match(nameLines[0], @"%vehicleName\s*=\s*""(.*)""");
            return match.Success ? match.Groups[1].Value : vehicleName;
        }

        /// <summary>Sets the label of a vehicle</summary>
        /// <param name="vehicleName"></param>
        /// <param name="vehicleLabel"></param>
        public static void SetVehicleLabel(string vehicleName, string vehicleLabel)
        {
            var path = string.Format("{0}{1}", GetVehicleFolder(vehicleName), ConfigurationManager.AppSettings["defVehicleNameFile"]);
            var lines = new[] { string.Format(@"%vehicleName = ""{0}"";", vehicleLabel) };
            File.WriteAllLines(path, lines);
        }

        /// <summary>Loads the different configuration files available for the vehicle</summary>
        /// <param name="vehicle"></param>
        public static void LoadVehicleConfigs(Vehicle vehicle)
        {
            vehicle.Configurations.Clear();
            foreach (var config in Directory.GetFiles(vehicle.Folder, "*.pc").Select(file => new VehicleConfig(vehicle, Path.GetFileName(file))))
            {
                config.Load();
                vehicle.Configurations.Add(config);
            }
        }

        /// <summary>Saves all the configurations of the vehicle</summary>
        /// <param name="vehicle"></param>
        public static void SaveVehicleConfigs(Vehicle vehicle, bool compress = true)
        {
            foreach (var config in vehicle.Configurations)
                config.Save(compress);
        }

        /// <summary>
        /// Copies all resources from a vehicle to the folder of another one
        /// </summary>
        /// <param name="source">The source vehicle</param>
        /// <param name="destination">The destination vehicle</param>
        public static void CopyResources(Vehicle source, Vehicle destination)
        {
            /* Null values provided */
            if (source == null || destination == null) return;

            source.CopyResourcesTo(destination.Name);
        }

        /// <summary>
        /// Copies all resources from a vehicle to the folder of another one
        /// </summary>
        /// <param name="sourceName"></param>
        /// <param name="destination"></param>
        public static void CopyResources(string sourceName, Vehicle destination)
        {
            if (string.IsNullOrEmpty(sourceName) || string.IsNullOrEmpty(destination.Name)) return;

            destination.CopyResourcesFrom(sourceName);
        }

        #endregion

        #region KeyedCollection

        protected override string GetKeyForItem(VehicleFile item)
        {
            return item.Name;
        }

        #endregion
    }
}
